package cn.iocoder.yudao.module.vlog.info.controller.app;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.business.basic.pojo.vo.UserSimpleVO;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.region.RegionUtils;
import cn.iocoder.yudao.framework.region.enums.RegionDataSet;
import cn.iocoder.yudao.module.api.member.user.MemberUserApi;
import cn.iocoder.yudao.module.api.product.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.api.shop.info.ShopInfoApi;
import cn.iocoder.yudao.module.api.vlog.info.enums.VLogStatusEnum;
import cn.iocoder.yudao.module.vlog.history.service.VLogBrowseHistoryService;
import cn.iocoder.yudao.module.vlog.info.bo.VLogMyActionBO;
import cn.iocoder.yudao.module.vlog.info.convert.VLogInfoConvert;
import cn.iocoder.yudao.module.vlog.info.dal.dataobject.VLogInfoDO;
import cn.iocoder.yudao.module.vlog.info.service.VLogInfoService;
import cn.iocoder.yudao.module.vlog.info.vo.*;
import cn.iocoder.yudao.module.vlog.product.service.VLogProductService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserLastShopId;
import static cn.iocoder.yudao.module.api.vlog.ErrorCodeConstants.*;

@Tag(name = "用户 App - 视频信息")
@RestController
@RequestMapping("/vlog/info")
@Validated
@Slf4j
public class AppVLogInfoController {

    @Resource
    private VLogInfoService vLogInfoService;
    @Resource
    private VLogBrowseHistoryService vLogBrowseHistoryService;
    @Resource
    private VLogProductService vLogProductService;
    @Resource
    private MemberUserApi memberUserApi;
    @Resource
    private ShopInfoApi shopInfoApi;

    @PostMapping("/create")
    @Operation(summary = "创建短视频")
    public CommonResult<Long> createInfo(@Valid @RequestBody AppVLogInfoCreateReqVO createReqVO) {
        return success(vLogInfoService.createInfo(getLoginUserLastShopId(), getLoginUserId(), createReqVO));
    }

    @PostMapping("/update-privacy")
    @Operation(summary = "设置短视频为公开/私密")
    public CommonResult<Boolean> updatePrivacy(@Valid @RequestBody AppVLogInfoPrivacyUpdateReqVO updateReqVO) {
        vLogInfoService.updatePrivacy(getLoginUserId(), updateReqVO);
        return success(true);
    }

    @PostMapping("/shelve")
    @Operation(summary = "视频上架")
    @Parameter(name = "id", description = "编号", required = true)
    public CommonResult<Boolean> shelve(@RequestParam("id") Long id) {
        VLogInfoDO infoDO = vLogInfoService.getInfo(id);
        if (infoDO.getStatus() == VLogStatusEnum.PENDING.getValue()) {
            throw exception(INFO_SHELVE_FORBIDDEN_PENDING);
        }
        if (infoDO.getStatus() == VLogStatusEnum.ENABLED.getValue()) {
            throw exception(INFO_SHELVE_FORBIDDEN_ENABLED);
        }
        VLogInfoStatusUpdateReqVO reqVO = new VLogInfoStatusUpdateReqVO();
        reqVO.setId(id);
        reqVO.setStatus(VLogStatusEnum.ENABLED.getValue());
        vLogInfoService.updateStatus(reqVO);
        return success(true);
    }

    @PostMapping("/unshelve")
    @Operation(summary = "视频下架")
    @Parameter(name = "id", description = "编号", required = true)
    public CommonResult<Boolean> unshelve(@RequestParam("id") Long id) {
        VLogInfoDO infoDO = vLogInfoService.getInfo(id);
        if (infoDO.getStatus() != VLogStatusEnum.ENABLED.getValue()) {
            throw exception(INFO_UNSHELVE_FORBIDDEN);
        }
        VLogInfoStatusUpdateReqVO reqVO = new VLogInfoStatusUpdateReqVO();
        reqVO.setId(id);
        reqVO.setStatus(VLogStatusEnum.DISABLED.getValue());
        vLogInfoService.updateStatus(reqVO);
        return success(true);
    }

    @GetMapping("/delete")
    @Operation(summary = "删除短视频")
    @Parameter(name = "id", description = "编号", required = true)
    public CommonResult<Boolean> deleteInfo(@RequestParam("id") Long id) {
        vLogInfoService.deleteInfo(getLoginUserId(), id);
        return success(true);
    }

    @GetMapping({"/get", "browse"})
    @Operation(summary = "获得短视频/浏览短视频")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    public CommonResult<AppVLogInfoRespVO> getInfo(@RequestParam("id") Long id) {
        Long userId = getLoginUserId();
        VLogInfoDO infoDO = vLogInfoService.getInfo(id);
        if (infoDO.getPrivacy() && !Objects.equals(infoDO.getUserId(), userId)) {
            throw exception(INFO_NOT_PUBLIC);
        }
        vLogBrowseHistoryService.createBrowseHistory(userId, id);
        AppVLogInfoRespVO respVO = BeanUtils.toBean(infoDO, AppVLogInfoRespVO.class);
        RegionUtils.autoAssignCity(RegionDataSet.ONLY_LATEST, respVO.getCityCode(), respVO);
        try {
            respVO.setShop(shopInfoApi.getShopInfo(infoDO.getShopId()));
            respVO.setUser(memberUserApi.getUser(userId));
            respVO.setSpuList(vLogProductService.getProductSpuList(id, 1));
        } catch (Exception e) {
            log.warn("[getInfo][id({}) 获得短视频 Shop、User 及 SpuIds 异常]", id, e);
        }
        return success(respVO);
    }

    @GetMapping("/page")
    @Operation(summary = "获得短视频分页")
    @PermitAll
    public CommonResult<PageResult<VLogInfoRespVO>> getInfoPage(@Valid AppVLogInfoPageReqVO pageReqVO) {
        PageResult<VLogInfoDO> pageResult = vLogInfoService.getEnabledInfoPage(pageReqVO);
        return toPageCommonResult(pageResult, false);
    }

    @GetMapping("/recommend-page")
    @Operation(summary = "获得推荐的短视频分页", description = "按经纬度获取附近的，先随机排序再按距离升序")
    @PermitAll
    public CommonResult<PageResult<VLogInfoRespVO>> getRecommendInfoPage(@Valid AppLatLngPageReqVO pageReqVO) {
        PageResult<VLogInfoDO> pageResult = vLogInfoService.getRecommendInfoPage(pageReqVO);
        return toPageCommonResult(pageResult, false);
    }

    @GetMapping("/my-page")
    @Operation(summary = "获得我发布的短视频分页")
    public CommonResult<PageResult<VLogInfoRespVO>> getMyInfoPage(@Valid AppVLogInfoPageReqVO pageReqVO) {
        PageResult<VLogInfoDO> pageResult = vLogInfoService.getMyInfoPage(getLoginUserId(), pageReqVO);
        return toPageCommonResult(pageResult, true);
    }

    @GetMapping("/liked-page")
    @Operation(summary = "获得我点赞的短视频分页")
    public CommonResult<PageResult<VLogInfoRespVO>> getLikedInfoPage(@Valid PageParam pageReqVO) {
        PageResult<VLogInfoDO> pageResult = vLogInfoService.getLikedInfoPage(getLoginUserId(), pageReqVO);
        return toPageCommonResult(pageResult, false);
    }

    @GetMapping("/favorite-page")
    @Operation(summary = "获得我收藏的短视频分页")
    public CommonResult<PageResult<VLogInfoRespVO>> getFavoriteInfoPage(@Valid PageParam pageReqVO) {
        PageResult<VLogInfoDO> pageResult = vLogInfoService.getFavoriteInfoPage(getLoginUserId(), pageReqVO);
        return toPageCommonResult(pageResult, false);
    }

    @GetMapping("/follow-page")
    @Operation(summary = "获得我关注的短视频分页")
    public CommonResult<PageResult<VLogInfoRespVO>> getFollowInfoPage(@Valid PageParam pageReqVO) {
        PageResult<VLogInfoDO> pageResult = vLogInfoService.getFollowInfoPage(getLoginUserId(), pageReqVO);
        return toPageCommonResult(pageResult, false);
    }

    @GetMapping("/friend-page")
    @Operation(summary = "获得我朋友的短视频分页")
    public CommonResult<PageResult<VLogInfoRespVO>> getFriendInfoPage(@Valid PageParam pageReqVO) {
        PageResult<VLogInfoDO> pageResult = vLogInfoService.getFriendInfoPage(getLoginUserId(), pageReqVO);
        return toPageCommonResult(pageResult, false);
    }

    @GetMapping("/comment-page")
    @Operation(summary = "获得我评论的短视频分页")
    public CommonResult<PageResult<VLogInfoRespVO>> getCommentInfoPage(@Valid PageParam pageReqVO) {
        PageResult<VLogInfoDO> pageResult = vLogInfoService.getCommentInfoPage(getLoginUserId(), pageReqVO);
        return toPageCommonResult(pageResult, false);
    }

    @GetMapping("/browse-history-page")
    @Operation(summary = "获得我看过的短视频分页")
    public CommonResult<PageResult<VLogInfoRespVO>> getBrowseHistoryInfoPage(@Valid PageParam pageReqVO) {
        PageResult<VLogInfoDO> pageResult = vLogInfoService.getBrowseHistoryInfoPage(getLoginUserId(), pageReqVO);
        return toPageCommonResult(pageResult, false);
    }

    private CommonResult<PageResult<VLogInfoRespVO>> toPageCommonResult(PageResult<VLogInfoDO> pageResult, boolean ignoreUser) {
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(PageResult.empty());
        }
        try {
            Map<Long, UserSimpleVO> users;
            if (ignoreUser) {
                users = new HashMap<>();
            } else {
                Set<Long> userIds = convertSet(pageResult.getList(), VLogInfoDO::getUserId);
                users = memberUserApi.getUserSimpleMap(userIds);
            }
            Set<Long> vlogIds = convertSet(pageResult.getList(), VLogInfoDO::getId);
            Map<Long, Collection<ProductSpuRespDTO>> spus = vLogProductService.getProductSpuMap(vlogIds);
            return success(VLogInfoConvert.INSTANCE.convertPage(pageResult, users, spus));
        } catch (Exception e) {
            log.warn("[getInfo][获得短视频分页 Shop、User 及 SpuList 异常]", e);
            return success(VLogInfoConvert.INSTANCE.convertPage(pageResult, new HashMap<>(), new HashMap<>()));
        }
    }

    @GetMapping("/check-actions")
    @Operation(summary = "检查自己是否已点赞、收藏、评论及关注")
    @Parameter(name = "ids", description = "短视频编号数组", required = true, example = "3,4")
    public CommonResult<List<VLogMyActionBO>> checkMyActions(@RequestParam("ids") List<Long> ids) {
        Long loginUserId = getLoginUserId();
        log.info("[checkMyActions][userId({}) ids({})]", loginUserId, ids);
        if (CollUtil.isEmpty(ids)) {
            return success(Collections.emptyList());
        }
        List<VLogMyActionBO> list = vLogInfoService.checkMyActions(loginUserId, ids);
        return success(list);
    }


}
